/**
 * 开源版本请务必保留此注释头信息，若删除捷码开源〔GEMOS〕官方保留所有法律责任追究！
 * 本软件受国家版权局知识产权以及国家计算机软件著作权保护（登记号：2018SR503328）
 * 不得恶意分享产品源代码、二次转售等，违者必究。
 * Copyright (c) 2020 gemframework all rights reserved.
 * http://www.gemframework.com
 * 版权所有，侵权必究！
 */
package com.gemframework.modules.prekit.sys;

import cn.hutool.core.date.BetweenFormater;
import cn.hutool.core.date.DateUtil;
import com.gemframework.common.constant.GemModules;
import com.gemframework.common.utils.GemDateUtils;
import com.gemframework.common.utils.GemSigarUtils;
import com.gemframework.controller.BaseController;
import com.gemframework.model.common.BaseResultData;
import com.gemframework.model.entity.bo.sigar.*;
import com.gemframework.model.response.sigar.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.hyperic.sigar.SigarException;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.math.BigDecimal;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.gemframework.model.enums.ExceptionCode.SYSTEM_EXCEPTION;

/**
 * @Title: SigarController
 * @Package: com.gemframework.modules.perkit.demo
 * @Date: 2020-04-16 13:36:13
 * @Version: v1.0
 * @Description: sigar全名是System Information Gatherer And Reporter
 * @Author: nine QQ 769990999
 * @Copyright: Copyright (c) 2020 wanyong
 * @Company: www.gemframework.com
 */
@Slf4j
@RestController
@RequestMapping(GemModules.PreKit.PATH_HOST+"/sigar")
public class SigarController extends BaseController {

    @Resource
    private GemSigarUtils gemSigarUtils;

    @GetMapping("/sysInfo")
    @RequiresPermissions("sigar:sysInfo")
    public BaseResultData sysInfo() {
        ServerProperty serverProperty;
        try {
            serverProperty = gemSigarUtils.property();
        } catch (UnknownHostException e) {
            return BaseResultData.ERROR(SYSTEM_EXCEPTION.getCode(),e.getMessage());
        }
        RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
        String startTime = GemDateUtils.formatTime(new Date(bean.getStartTime()));

        String formatBetween = DateUtil.formatBetween(new Date(bean.getStartTime()),new Date(), BetweenFormater.Level.SECOND);
        HostJvmResponse response = HostJvmResponse.builder()
                .appHome(serverProperty.getUserDir())
                .javaHome(serverProperty.getJavaHome())
                .javaVersion(serverProperty.getJavaVersion())
                .jvmName(serverProperty.getJvmName())
                .jvmStartTime(startTime)
                .jvmRunTime(formatBetween)
                .build();
        return BaseResultData.SUCCESS(response);
    }

    public static void main(String[] args) throws InterruptedException {
        RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
        //睡眠1s
        Thread.currentThread().sleep(3000);
        String formatBetween = DateUtil.formatBetween(new Date(),new Date(bean.getStartTime()), BetweenFormater.Level.SECOND);
    log.info(formatBetween);
    }

    @GetMapping("/memory")
    @RequiresPermissions("sigar:memory")
    public BaseResultData memory() {
        ServerMemory info;
        try {
            info = gemSigarUtils.memory();
        } catch (SigarException e) {
            return BaseResultData.ERROR(SYSTEM_EXCEPTION.getCode(),e.getMessage());
        }
        double hostMemory = new BigDecimal(info.getTotal()/1024).setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue();
        double hostMemoryFree = new BigDecimal(info.getFree()/1024).setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue();
        double hostUseMemory = new BigDecimal(info.getUsed()/1024).setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue();
        double hostUsePercent = new BigDecimal(hostUseMemory/hostMemory*100).setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue();
        double swapMemory = new BigDecimal(info.getSwapTotal()/1024).setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue();
        double swapMemoryFree = new BigDecimal(info.getSwapFree()/1024).setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue();
        double swapUseMemory = new BigDecimal(info.getSwapUsed()/1024).setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue();
        double swapUsePercent = new BigDecimal(swapUseMemory/swapMemory*100).setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue();
        HostRamResponse response = HostRamResponse.builder()
                .hostMemory(hostMemory)
                .hostMemoryFree(hostMemoryFree)
                .hostMemoryUsed(hostUseMemory)
                .hostUsePercent(hostUsePercent)
                .swapMemory(swapMemory)
                .swapMemoryFree(swapMemoryFree)
                .swapMemoryUsed(swapUseMemory)
                .swapUsePercent(swapUsePercent)
                .build();
        return BaseResultData.SUCCESS(response);
    }

    @GetMapping("/cpuInfo")
    @RequiresPermissions("sigar:cpuInfo")
    public BaseResultData cpuInfo() {
        List<ServerCPUInfo> list;
        try {
            list = gemSigarUtils.cpu();
        } catch (SigarException e) {
            return BaseResultData.ERROR(SYSTEM_EXCEPTION.getCode(),e.getMessage());
        }
        double free = 0;
        double sysUsage = 0;
        double userUsage = 0;
        if(list!=null&&list.size()>0){
            for(ServerCPUInfo cpu : list){
                free += cpu.getFree();
                sysUsage += cpu.getSysUsed();
                userUsage += cpu.getUserUsed();
            }
        }
        HostCpuResponse response = HostCpuResponse.builder()
                .coreNum(list.size())
                .free(new BigDecimal(free/8*100).setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue())
                .sysUsage(new BigDecimal(sysUsage/8*100).setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue())
                .userUsage(new BigDecimal(userUsage/8*100).setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue())
                .build();
        ;
        return BaseResultData.SUCCESS(response);
    }

    @GetMapping("/osInfo")
    @RequiresPermissions("sigar:osInfo")
    public BaseResultData osInfo() {
        ServerProperty serverProperty;
        ServerOSInfo serverOSInfo;
        try {
            serverProperty = gemSigarUtils.property();
            serverOSInfo = gemSigarUtils.os();
        } catch (UnknownHostException e) {
            return BaseResultData.ERROR(SYSTEM_EXCEPTION.getCode(),e.getMessage());
        }
        HostInfoResponse response = HostInfoResponse.builder()
                .arch(serverOSInfo.getArch())
                .hostAddr(serverProperty.getIpAddr())
                .hostName(serverProperty.getComputerName())
                .hostOs(serverOSInfo.getVendor()+","+serverOSInfo.getVersion())
                .build();
        return BaseResultData.SUCCESS(response);
    }

    @GetMapping("/diskInfo")
    @RequiresPermissions("sigar:diskInfo")
    public BaseResultData diskInfo() {
        List<ServerDiskInfo> list;
        try {
            list = gemSigarUtils.file();
        } catch (SigarException e) {
            return BaseResultData.ERROR(SYSTEM_EXCEPTION.getCode(),e.getMessage());
        }
        List<HostDiskResponse> responses = new ArrayList<>();
        if(list!=null&&list.size()>0){
            for(ServerDiskInfo disk : list){
                HostDiskResponse hostDiskResponse = HostDiskResponse.builder()
                        .dirName(disk.getDirName())
                        .fileType(disk.getDevType())
                        .sysType(disk.getSysType())
                        .total(new BigDecimal(disk.getTotal()/(1024*1024)).setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue())
                        .avail(new BigDecimal(disk.getAvail()/(1024*1024)).setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue())
                        .used(new BigDecimal(disk.getUsed()/(1024*1024)).setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue())
                        .usePercent(new BigDecimal(disk.getUsePercent()).setScale(2,   BigDecimal.ROUND_HALF_UP).doubleValue())
                        .build();
                responses.add(hostDiskResponse);
            }
        }
        return BaseResultData.SUCCESS(responses);
    }

    @GetMapping("/network")
    @RequiresPermissions("sigar:network")
    public BaseResultData network() {
        List<ServerNetwork> info;
        try {
            info = gemSigarUtils.net();
        } catch (SigarException e) {
            return BaseResultData.ERROR(SYSTEM_EXCEPTION.getCode(),e.getMessage());
        }
        return BaseResultData.SUCCESS(info);
    }

}